package com.vision.core.cl.mvp;

import java.util.List;

import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.vision.core.cl.Callback;
import com.vision.core.cl.ui.ConfirmDialogHandler;
import com.vision.core.cl.ui.View;
import com.vision.core.cm.serv.rpc.AbstractServiceAsync;

/**
 * 
 * @author Mark
 *
 */
public abstract class AbstractPresenter<T> implements Presenter<T> {

	protected View<T> view;
	
	protected AbstractServiceAsync<T> service;
	
	public AbstractPresenter(AbstractServiceAsync<T> service) {
		this.service = service;
	}
	
	// Abstract Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	/**
	 * Returns a text used to display <tt>obj</tt>.
	 * 
	 * @param obj
	 * @return
	 */
	protected abstract String getDisplayText(T obj);
	
	// Presenter Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Override
	public void setView(View<T> view) {
		this.view = view;
	}
	
	@Override
	public void onRefreshClicked(SelectEvent e) {
		loadData();
	}

	@Override
	public void onAddClicked(SelectEvent e) {
		// Empty. To be implemented by subclasses.
	}

	@Override
	public void onDeleteClicked(SelectEvent e) {
		final T selected = view.getSelected();
		if (selected == null)
			return;
		
		view.confirm("Confirm Delete", "Are you sure you want to delete '" + getDisplayText(selected) + "'?",
			new ConfirmDialogHandler() {
				@Override
				public void onYes(HideEvent event) {
					view.mask("Deleting " + getDisplayText(selected) + "...");
					service.delete(selected, new Callback<T>(view) {
						@Override
						protected void handleSuccess(T result) {
							view.remove(result);
							
							// Clear the form editor if necessary
							T inEditor = view.getInEditor();
							if (inEditor != null && inEditor.equals(result))
								view.edit(null);
						}
					});
				}
			}
		);
	}
	
	@Override
	public void loadData() {
		view.mask("Loading...");
		service.getAll(new Callback<List<T>>(view) {
			@Override
			protected void handleSuccess(List<T> result) {
				view.setData(result);
				view.edit(null);
			}
		});
	}

	@Override
	public void onSelect(final T object) {
		if (object == null)
			return;
		
		if (view.isDirty()) { // If there are unsaved changes in the form
			view.confirm("Unsaved Changes", "There are unsaved changes. Would you like to continue loading?",
				new ConfirmDialogHandler() {
					@Override
					public void onYes(HideEvent event) {
						view.edit(object);
					}
				}
			);
		} else {
			view.edit(object);
		}
	}

	@Override
	public void onSaveClicked(SelectEvent e) {
		T object = view.getInEditor();
		if (!view.isFormValid() || object == null)
			return;
		
		view.mask("Updating...");
		service.update(object, new Callback<T>(view) {
			@Override
			protected void handleSuccess(T result) {
				view.update(result);
				view.edit(result);
			}
		});
	}

	@Override
	public void onCancelClicked(SelectEvent e) {
		view.edit(null);
	}

	@Override
	public void onActivateClicked(SelectEvent e) {
		// Empty. To be implemented by presenters whose models support activation/deactivation.
	}

}
